﻿using Microsoft.IdentityModel.Tokens;
using NetTaste;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

/*
 * 杭州允博条码科技有限公司
 * 杭州聚识自动化科技有限公司
 * 说明：Token帮助类，主要是生成Token，和解析Token的功能
 * 创建时间：2023.07.03
 * 创建人：蔡文奇
 * 最后修改时间 2023.07.03
 */

namespace YunZiChanApi.Yunbo
{
    /// <summary>
    /// Token帮助类，主要是生成Token，和解析Token的功能
    /// </summary>
    public class TokenHelper
    {
        /// <summary>
        /// 配置文件appsettings.json
        /// </summary>
        private readonly IConfiguration _configuration;
        /// <summary>
        /// 需要解析的token
        /// </summary>
        private readonly string _jwtToken = string.Empty;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="configuration"></param>
        public TokenHelper(IConfiguration configuration)
        {
            _configuration = configuration;
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="jwtToken"></param>
        public TokenHelper(IConfiguration configuration, string jwtToken)
        {
            _configuration = configuration;
            _jwtToken = jwtToken;
        }

        /// <summary>
        /// 生成Token  通常登录时调用
        /// </summary>
        /// <param name="claims"></param>
        /// <returns></returns>
        public string GenerateToken(IEnumerable<Claim> claims)
        {
            // 2. 从 appsettings.json 中读取SecretKey
            var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:SecretKey"]));
            // 3. 选择加密算法
            var algorithm = SecurityAlgorithms.HmacSha256;
            // 4. 生成Credentials
            var signingCredentials = new SigningCredentials(secretKey, algorithm);
            // 5. 从 appsettings.json 中读取Expires
            var expires = Convert.ToDouble(_configuration["JWT:Expires"]);
            // 6. 根据以上，生成token
            var Token = new JwtSecurityToken(
                    issuer: _configuration["JWT:Issuer"],                   //发布者
                    audience: _configuration["JWT:Audience"],               //接收者
                    claims: claims,                                         //存放的用户信息
                    notBefore: DateTime.UtcNow,                             //发布时间
                    expires: DateTime.UtcNow.AddHours(expires),             //有效期设置为24小时
                    signingCredentials                                      //数字签名
                );
            // 7. 将token变为string
            var jwtToken = new JwtSecurityTokenHandler().WriteToken(Token);
            return jwtToken;
        }

        /// <summary>
        /// 解析token 获取Claim对象 通常控制器中需要获取Token的参数使用
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Claim> GetClaim()
        {
            // 创建一个 JwtSecurityTokenHandler 实例
            var tokenHandler = new JwtSecurityTokenHandler();

            var validationParameters = new TokenValidationParameters
            {
                // 配置密钥、发行者、接收者等参数
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = _configuration["JWT:Issuer"],
                ValidAudience = _configuration["JWT:Audience"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:SecretKey"]))
            };

            // 解析 JWT Token
            ClaimsPrincipal claimsPrincipal;
            try
            {
                claimsPrincipal = tokenHandler.ValidateToken(_jwtToken.Replace("bearer ", ""), validationParameters, out _);
            }
            catch (Exception ex)
            {
                // Token 验证失败，处理异常...
                return Enumerable.Empty<Claim>();
            }

            // 获取 JWT 中的所有声明
            IEnumerable<Claim> claims = claimsPrincipal.Claims;

            return claims;
        }


        #region 调用示例
        // 在登录的控制器中使用

        //// 1. 定义需要使用到的Claims
        //var claims = new[]
        //{
        //        //把用户的id加密进去，使用的时候可以从token里解密拿出来
        //        new Claim("Id", "1"),
        //        //也可以多传几个参数
        //        new Claim("UserName", "tiaoma888")
        //    };
        //// 实例化TokenHelper对象
        //TokenHelper tokenHelper = new(_configuration);
        //// 生成Token
        //string jwtToken = tokenHelper.GenerateToken(claims);

        // 在需要访问的控制器中调用

        //// 获取Token
        //var token = HttpContext.Request.Headers["Authorization"].ToString();
        //// 实例化TokenHelper对象
        //TokenHelper tokenHelper = new(_configuration, token);
        //// 解析Token字符串 获取Claims集合
        //IEnumerable<Claim> claims = tokenHelper.GetClaim();
        //// 获取Claims集合 自定义的变量
        //string customClaimValue = claims.FirstOrDefault(c => c.Type == "Id")?.Value;
        //string UserName = claims.FirstOrDefault(c => c.Type == "UserName")?.Value; 
        #endregion

    }
}
